﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ZaidimasSandelys.Models.DataStructures;
using ZaidimasSandelys.Models.Interfaces;

namespace ZaidimasSandelys.CustomDrawTools
{
    public enum VisualType : short
    {
        OuterSpace = 0,     // Nenaudojama srytis,                  Prioritetas 0
        Wall = 1,           // Siena                                Prioritetas 1
        Floor = 2,          // Grindys,                             Prioritetas 2
        Target = 3,         // Vieta, kurion reikia nustumti dėžę   Prioritetas 3
        TargetHC = 4,       // Metalinės dėžės vieta                Prioritetas 4
        Container = 5,      // Dėžė                                 Prioritetas 4
        HeavyContainer = 6, // Metalinis konteineris,               Prioritetas 5
        Autocar = 7,        // Autokaras                            Prioritetas 6   ForkLiftTruck

/*  Tolimesniam žaidimo praplėtimui
        Keys = 8,           // Raktai                               Prioritetas 7
        Doors = 9,          // Durys                                Prioritetas 8
        Pass = 10,          // Leidimas                             Prioritetas 9
 */
        Person = 100,        // Žmogeliukas (dėžių stumdytojas)      Prioritetas 10
    }

    /// <summary>
    /// Bazinė klasė (visi žaidimo elementai yra šios klasės plėtiniai), kurioje aprašomi žaidimų elementų savybės
    /// </summary>
    public abstract class AllocatedVisual : DrawingVisual, IGameElement
    {
        public static readonly VisualType[] SinglePointElements = new VisualType[] {
            VisualType.OuterSpace, VisualType.Wall, VisualType.Floor, VisualType.Target 
        };

        /// <summary>
        /// Kairio viršutinio kampo loginės koordinatės
        /// </summary>
        public Movement Position { get; protected set; }

        /// <summary>
        /// Elemento tipas <see cref="VisualType"/>
        /// </summary>
        public VisualType ImgType { get; protected set; }

        /// <summary>
        /// <code>true</code> - elementą galima stumdyti
        /// </summary>
        public bool CanMove { get; set; }

        /// <summary>
        /// Konstruktoriai
        /// </summary>
        /// <param name="imgType">Objekto tipas <see cref="VisualType"/></param>
        private AllocatedVisual(VisualType imgType)
        {
            this.ImgType = imgType;
            this.CanMove = false;
        }
        protected AllocatedVisual(Movement position, VisualType imgType = VisualType.OuterSpace): this(imgType)
        {
            this.Position = new Movement(position);
        }
        protected AllocatedVisual(int x, int y, VisualType imgType = VisualType.OuterSpace): this(imgType)
        {
            this.Position = new Movement(x, y);
        }

        public abstract void DrawItself(Size multiplicator);
        protected virtual void DrawItself(Size multiplicator, Brush drawingBrush, Pen drawingPen)
        {
            using (DrawingContext dc = this.RenderOpen())
            {
                Size squareSize = new Size(multiplicator.Width, multiplicator.Height);
                Point leftTop = Position.GetDrawingPoint(multiplicator);
                dc.DrawRectangle(drawingBrush, drawingPen, new Rect(leftTop, squareSize));
            }
        }

        /// <summary>
        /// Sukuria reikiamą <code>AllocatedVisual</code> tipą. Funkcija grąžina NULLą jei tipo reikšmė neteisinga.
        /// </summary>
        /// <param name="x">Kairio viršutinio kampo koordinatė X</param>
        /// <param name="y">Kairio viršutinio kampo koordinatė Y</param>
        /// <param name="imgType">Elemento tipas nuskaitytas iš duomenų bazės <see cref="VisualType"/></param>
        /// <returns>Sukurtas <code>AllocatedVisual</code> arba NULLas</returns>
        public static AllocatedVisual CreateAllocatedVisual(short x, short y, short imgType)
        {
            switch (imgType)
            {
                case (int)VisualType.OuterSpace:
                    return new OuterSpaceVisual(x, y);
                case (int)VisualType.Wall:
                    return new WallVisual(x, y);
                case (int)VisualType.Floor:
                    return new FloorVisual(x, y);
                case (int)VisualType.Target:
                    return new TargetVisual(x, y);
                case (int)VisualType.TargetHC:
                    return new TargetHcVisual(x, y);
                case (int)VisualType.Container:
                    return new ContainerVisual(x, y);
                case (int)VisualType.HeavyContainer:
                    return new HeavyContainerVisual(x, y);
                case (int)VisualType.Autocar:
                    return new AutocarVisual(x, y);
                case (int)VisualType.Person:
                    return new PersonVisual(x, y);
                default:
                    return null;
            }
        }

        protected virtual Brush GetBitmapBrush(string name)
        {
            string uri = String.Format("pack://application:,,,/Resources/Images/{0}", name);
            var source = new BitmapImage(new Uri(uri));
            return new ImageBrush(source);
        }

        public short X
        {
            get { return (short)Position.Width; }
        }

        public short Y
        {
            get { return (short)this.Position.Height; }
        }

        public short ImgTypeCode 
        {
            get { return (short)this.ImgType; }
        }

        public static VisualType SafeConvertToVisualType(short code)
        {
            try
            {
                return (VisualType)code;
            }
            catch (Exception)
            {
                return VisualType.OuterSpace;
            }
        }
    }
}
